#pragma once

#include<memory>
#include<iostream>
#include<jsoncpp/json/json.h>


 //#define SelfDefine 1

//Tcp面向字节流
//无法保证package就是一个独立的完整的报文


namespace Proctocol
{

    const std::string ProtSep=" ";
    const std::string LineSep="\n";
    //"len\nx op y\n":打包---len代表的是x op y的长度
    std::string Encode(std::string& message)
    {
        std::string len=std::to_string(message.size());
        std::string package=len+LineSep+message+LineSep;
        return package;
    }
    //"len\nx op y\n":解包要考虑是否是一个完整的包裹
    //"len":
    //"len\":
    //"len\n":
    //"len\nx ":
    //"len\nx o":
    //"len\nx op":
    //"len\nx op y":
    //"len\nx op y\n":

    bool Decode(std::string& package,std::string*message)
    {
        auto pos=package.find(LineSep);
        if(pos==std::string::npos)return false;
        std::string len=package.substr(0,pos);//len的长度
        int total=len.size()+std::stoi(len)+2*LineSep.size();//一个完整报文的长度
        if(package.size()<total)//当前报文的长度小于一个完整报文就说明报文不完整
            return false;
        *message=package.substr(pos+LineSep.size(),std::stoi(len));
        package.erase(0,total);//抛除掉解析掉的一个完整报文
        return true;
    }
    


    class Request
    {
    public:
        Request() 
            : _data_x(0), _data_y(0), _oper(0)
        {}
        Request(int x, int y, char op)
            : _data_x(x), _data_y(y), _oper(op)
        {
        }
        ~Request() {}
        void Print()
        {
            std::cout << "_data_x: " << _data_x << std::endl;
            std::cout << "_data_y: " << _data_y << std::endl;
            std::cout << "_oper: " << _oper << std::endl;
        }
        void AddPrint()
        {
            _data_x++;
            _data_y++;
        }

        int GetX()
        {
            return _data_x;
        }

        int GetY()
        {
            return _data_y;
        }

        char Getoper()
        {
            return _oper;
        }

        // 序列化:组合字符串
        bool Serialize(std::string *out) // x op y
        {
        #ifdef SelfDefine
            *out = std::to_string(_data_x) + ProtSep + _oper + ProtSep + std::to_string(_data_y);
            return true;

        #else
            Json::Value root;
            root["datax"]=_data_x;
            root["datay"]=_data_y;
            root["oper"]=_oper;

            Json::StyledWriter writer;
            *out=writer.write(root);
            return true;
        #endif
        }

        // 反序列化:分割字符串
        bool Deserialize(std::string &in)
        {
        #ifdef SelfDefine
            auto left = in.find(ProtSep);
            if (left == std::string::npos)
                return false;

            auto right = in.rfind(ProtSep);
            if (right == std::string::npos)
                return false;

            _data_x = std::stoi(in.substr(0, left));// s.substr(pos, len)
            _data_y = std::stoi(in.substr(right + ProtSep.size())); //?
            std::string oper = in.substr(left + ProtSep.size(), right - (left+ProtSep.size()));//？？？？
            if (oper.size() != 1)
                return false;
            else
            {
                _oper = oper[0];
                return true;
            }
        #else
            Json::Value root;
            Json::Reader reader;
            bool res=reader.parse(in,root);
            if(res)
            {
                _data_x=root["datax"].asInt();
                _data_y=root["datay"].asInt();
                _oper=root["oper"].asInt();
                return true;
            }
            else return false;
        #endif
        }

    private:
        //_data_x _oper _data_y

        // 报文的自描述字段
        //"len\nx op y\n":\n不属于报文的一部分，约定
        // 其实就是在做字符串处理

        int _data_x; // 第一个参数
        int _data_y; // 第二个参数
        char _oper;  // + - * /
    };

    class Response
    {
    public:
        Response() 
            : _result(0), _code(0)
        {}
        Response(int result, int code)
            : _result(result), _code(code)
        {
        }
        ~Response() {}

        int Setresult(int res)
        {
            _result=res;
            return _result;
        }

        int Setcode(int code)
        {
            _code=code;
            return _code;
        }

        int Getresult()
        {
            return _result;
        }

        int Getcode()
        {
            return _code;
        }

        // 序列化
        bool Serialize(std::string *out) //_result _code
        {
        #ifdef SelfDefine
            *out = std::to_string(_result) + ProtSep + std::to_string(_code);
            return true;
        #else
            Json::Value root;
            root["result"]=_result;
            root["code"]=_code;
            Json::StyledWriter writer;
            *out=writer.write(root);
            return true;
        #endif
        }

        // 反序列化
        bool Deserialize(std::string &in)
        {
        #ifdef SelfDefine
            auto pos = in.find(ProtSep);
            if (pos == std::string::npos)
                return false;

            _result = std::stoi(in.substr(0, pos));
            _code = std::stoi(in.substr(pos + ProtSep.size()));
            return true;
        #else
            Json::Value root;
            Json::Reader reader;
            bool res=reader.parse(in,root);
            if(res)
            {
                _result=root["result"].asInt();
                _code=root["code"].asInt();
                return true;
            }
            else return false;
        #endif
        }

    private:
        //_result _code
        // 报文自描述字段
        //"len\n_result _code\n"

        int _result; // 运算结果
        int _code;   // 运算状态
    };

    class Factory
    {
    public:
        std::shared_ptr<Request> BuildRequest()
        {
            std::shared_ptr<Request> req = std::make_shared<Request>();
            return req;
        }

        std::shared_ptr<Request> BuildRequest(int x, int y, char op)
        {
            std::shared_ptr<Request> req = std::make_shared<Request>(x, y, op);
            return req;
        }

        std::shared_ptr<Response> BuildResponse()
        {
            std::shared_ptr<Response> resp = std::make_shared<Response>();
            return resp;
        }

        std::shared_ptr<Response> BuildResponse(int result, int code)
        {
            std::shared_ptr<Response> resp = std::make_shared<Response>(result, code);
            return resp;
        }
    };
}